# @Authority李亚泽
from scipy.stats import chisquare

def strategy(strategyNum,sortedCountList,userStrategy=None):
    """
    # 由于卡方优度拟合检验要求每项的频数不可以小于5，不然结果不可信，所以要针对不同参数做不同的分组策略
    # 内置的三个分组策略，未完成
    # params：
    # strategyNum:要选择的内置策略，只可为1、2、3，实际上只有1可用。
    # sortedCountList:难以表述...
    # userStrategy:用户自定义的策略，参照s_1
    """
    def s_1(sortedCountList):
        result=[[],[],[],[],[],[]]
        for item in sortedCountList:
            if   len(result[0]) < 1:
                result[0].append(item)
            elif len(result[1]) < 3:
                result[1].append(item)
            elif len(result[2]) < 3:
                result[2].append(item)
            elif len(result[3]) < 5:
                result[3].append(item)
            elif len(result[4]) < 4:
                result[4].append(item)
            else:
                result[5].append(item)
        return result
    def s_2(sortedCountList):
        pass
    def s_3(sortedCountList):
        pass


    strategyDict={1:s_1,2:s_2,3:s_3}
    if userStrategy==None:    
        return strategyDict[strategyNum](sortedCountList)
    else:
        return userStrategy(sortedCountList)


def getDistribute(string_0,strategyNum=1,userStrategy=None):
    """
    计算一字符串的字符分布
    string_0：要计算字符分布的字符串
    strategyNum:要选择的内置策略，只可为1、2、3，实际上只有1可用。
    userStrategy:用户自定义的策略
    """
    asciiList = []
    countList = []
    uniqueAsciiList = []
    # 字符转化成数字
    for x in string_0:
        asciiList.append(ord(x))
    # 计算数组长度
    length = len(asciiList)
    # 计算每个数出现概率
    for item in asciiList:
        uniqueAsciiList.append(item)
        if uniqueAsciiList.count(item) > 1:
            pass
        else:            
           countList.append(asciiList.count(item))
    for x in range(length, 256):
        countList.append(0)
    # 降序排列
    sortedCountList = sorted(countList, reverse=True)
    # 序列分组
    sumList = []
    result=strategy(strategyNum,sortedCountList,userStrategy=userStrategy)
    # 组内求和,得到概率序列
    for x in range(len(result)):
        sumList.append(round(sum(result[x]),3))

    return sumList


def dealdata(trainingList,strategyNum=1,userStrategy=None):
    """
    处理一整个要预测的样本集,训练阶段调用
    trainingList：要用于训练的样本集
    strategyNum:要选择的内置策略，只可为1、2、3，实际上只有1可用。
    userStrategy:用户自定义的策略
    """
    # 创建后面用于储存数据的列表
    resultList=[[],[],[],[],[],[],[],[]]
    ICDList=[]

    # 记录数据个数
    num = len(trainingList)
    # 对样本中的每一个字符串进行训练
    for x in trainingList:
        string_0=x
        string_0.replace(" ","")
        if string_0==""or string_0==" ":
            continue
        sum_0 = getDistribute(string_0,strategyNum=strategyNum,userStrategy=userStrategy)

        for index in range(len(sum_0)):
            resultList[index].append(sum_0[index])


    for x in resultList:
        if x !=[]:
            ICDList.append(sum(x)/num)    
    
    return ICDList

def chi2Rst(ICDList,stringDistribute):

    # 计算卡方结果
    # params：
    # ICDList:理想字符分布
    # stringDistribute:样本字符分布
    # return:
    # pvalue应该视为待测样本和理想情况的符合程度
	for index in range(6):
		# 确保不出现除0的问题
		if ICDList[index]==0:
			ICDList[index]=1
	return chisquare(f_obs=stringDistribute,f_exp=ICDList)

def makeDecesion(threshold,p_value_list):
    """
    决策函数
    params:
    threshold:决策阈值，小于该值会被判为负类
    p_value_list:p值的list
    """
    decesionRst=[]
    for x in p_value_list:
        if x<=threshold:
            decesionRst.append(0)
        else:
            decesionRst.append(1)
    return decesionRst
def makeDecsionByScore(Score,p_value_list):
    """
    根据指定阈值列表做决策
    为了绘制ROC曲线准备的函数
    params:
    Score:阈值列表
    其他参数同上
    """
    temp=[]
    for threshold in Score:
        temp.append(makeDecesion(threshold, p_value_list))
    return temp


